# -*- coding: utf-8 -*-
from django.http import HttpResponse, HttpResponseForbidden
from django.utils import simplejson
from django.core.validators import ValidationError
from django.core.serializers import serialize
from django.views.generic import list_detail
from datetime import datetime
import django
if django.VERSION > (0, 96, None):
    from django.utils.translation import ugettext as _
else:
    from django.utils.translation import gettext_lazy as _


def get_user(request):
    return request.user


#def get_user(request):
#    try:
#        # access from key (用key访问)
#        return APIKey.objects.get(key=request["_key"]).user
#    except (KeyError, ObjectDoesNotExist), e:
#        # access from  session (用session访问)
#        return request.user


class Resource(object):

    cannot_update_fields = ['id']
    cannot_create_fields = ['id']
    cannot_see_fields = []

    def before_get_list(self, request, Class):
        """run some extra code before get_list"""
#        if not get_user(request).has_perm("%s.see_%s"%(app, model)):
#            return HttpResponseForbidden(_('没有查看权限'))

    def get_list(self, request, Class):
        self.before_get_list(request, Class)
        d = {}
        for field in Class._meta.fields:
            try:
                attname = request.GET[field.attname]
            except KeyError:
                pass
            else:
                try:
                    d[field.attname] = field.to_python(attname)
                except ValidationError:
                    # 也可以直接pass
                    response = HttpResponse(_('参数错误，不能完成请求'))
                    response.status_code = 501
                    return response
        result = Class.objects.filter(**d)
        format = request.GET.get("_format", "json")
        fields = request.GET.getlist("_fields")
        options = {"ensure_ascii": False}
        if format == "xml" or django.VERSION > (0, 96, None):
            if fields:
                options["fields"] = list(set(fields) - set(self.cannot_see_fields))
            elif self.cannot_see_fields:
                fields = [f.attname for f in Class._meta.fields]
                options["fields"] = list(set(fields) - set(self.cannot_see_fields))

        if format == "json":
            data = serialize('json', result, **options)
            return HttpResponse(data, mimetype="application/javascript")
        elif format == "xml":
            data = serialize('xml', result, **options)
            return HttpResponse(data, mimetype="application/xml")
        else:
            return list_detail.object_list(request, result, allow_empty=True,
                    extra_context={"fields": options.get("fields")})

    def before_create(self, request, obj):
        """"""
#        if hasattr(obj, 'create_user'):
#            obj.create_user = get_user(request)
#        if hasattr(obj, 'create_time'):
#            obj.create_time = datetime.today()

    def create(self, request, Class):
        if not get_user(request).has_perm("%s.add_%s"%(app, model)):
            return HttpResponseForbidden(_('没有添加权限'))
        d = {}
        for field in Class._meta.fields:
            if field.attname in self.cannot_create_fields:
                continue
            try:
                attname = request.GET[field.attname]
            except KeyError:
                pass
            else:
                try:
                    d[field.attname] = field.to_python(attname)
                except ValidationError:
                    response = HttpResponse(_('参数错误，不能完成请求'))
                    response.status_code = 501
                    return response
        try:
            obj = Class.objects.create(**d)
            self.before_create(obj)
            obj.save()
        except:
            response = HttpResponse(_('参数错误，不能完成请求'))
            response.status_code = 501
            return response
        return HttpResponse(_('成功添加一条记录'))

    def before_read(self, request, obj):
        """run some extra code before read"""
        # 需要自己在 models.py 中设置查看权限
        # e.g. permissions = (("see_termindex", "Can see TermIndex"))
#        if not get_user(request).has_perm("%s.see_%s" % (
#                obj._meta.app_label, obj.__class__.__name__.lower())):
#            return HttpResponseForbidden(_('没有查看权限'))

    def read(self, request, obj_list):
        self.before_read(request, obj_list[0])
        # 为了方便返回了一个长度为1的list, 如何序列化一个对象而不是query_set?
        format = request.GET.get("_format", "json")
        fields = request.GET.getlist("_fields")
        options = {"ensure_ascii": False}
        if format == "xml":
            if fields:
                options["fields"] = list(set(fields) - set(self.cannot_see_fields))
            elif self.cannot_see_fields:
                fields = [f.attname for f in Class._meta.fields]
                options["fields"] = list(set(fields) - set(self.cannot_see_fields))


        if format == "json":
            data = serialize('json', obj_list, **options)
            return HttpResponse(data[1:-1], mimetype="application/javascript")
        elif format == "xml":
            data = serialize('xml', obj_list, **options)
            return HttpResponse(data, mimetype="application/xml")
        else:
            return list_detail.object_detail(request, obj_list,
                    extra_context={"fields": options.get("fields")})

    def before_update(self, request, obj):
        """"""
        # 同步设置当前修改时间和用户
#        if hasattr(obj, 'update_time'):
#            obj.update_time = datetime.today()
#        if hasattr(obj, 'update_user'):
#            obj.update_user = get_user(request)

    def update(self, request, obj):
        if not get_user(request).has_perm("%s.change_%s" % (
                obj._meta.app_label, obj.__class__.__name__.lower())):
            return HttpResponseForbidden(_('没有修改权限'))

        for field in obj._meta.fields:
            if field.attname in self.cannot_update_fields:
                continue
            try:
                value = request.POST[field.attname]
            except KeyError:
                pass
            else:
                try:
                    setattr(obj, field.attname, field.to_python(value))
                except ValidationError:
                    response = HttpResponse(_('参数错误，不能完成请求'))
                    response.status_code = 501
                    return response
        self.before_update(request, obj)
        obj.save()
        return HttpResponse(_('修改成功'))

    def delete(self, request, obj):
        if not get_user(request).has_perm("%s.delete_%s" % (
                obj._meta.app_label, obj.__class__.__name__.lower())):
            return HttpResponseForbidden(_('没有删除权限'))
        obj.delete()
        return HttpResponse(_('删除成功'))


resource_registry = {}
# e.g. {Model: {'api1': resource1, 'api2': resource2}}


def register(key, model, ResourceClass=Resource):
    try:
        resource_registry[model][key]
        raise 'model %s already registered.' % model.__name__
    except KeyError:
        resources = resource_registry.setdefault(model, {})
        resources[key] = ResourceClass()
